package com.sumauto.view;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.graphics.RectF;
import android.support.annotation.IntDef;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;
import android.view.ViewGroup;

import com.sumauto.R;

/*
 * Copyright:
 * Author: 		Lincoln
 * Description:
 * History:		2019/02/28
 */
public class SupperBubbleLayout extends ViewGroup {
    public static final int LEFT = 1;
    public static final int TOP = 2;
    public static final int RIGHT = 3;
    public static final int BOTTOM = 4;

    @IntDef({LEFT, TOP, RIGHT, BOTTOM})
    private @interface Direction {
    }

    /**
     * 圆角大小
     */
    private int mRadius;

    /**
     * 三角形的方向
     */
    @Direction
    private int mDirection;

    /**
     * 三角形的底边中心点
     */
    private Point mDatumPoint;

    /**
     * 三角形位置偏移量(默认居中)
     */
    private int mOffsetUnits;
    private int mTriangleUnits;

    private Paint mBorderPaint;

    private Path mPath;

    private RectF mRect;

    private int mTriangleSize;

    public SupperBubbleLayout(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init(context, attrs);
    }

    private void init(Context context, AttributeSet attrs) {
        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.SupperBubbleLayout);
        //背景颜色
        int backGroundColor = ta.getColor(R.styleable.SupperBubbleLayout_bubble_background, Color.WHITE);
        //阴影颜色
        int shadowColor = ta.getColor(R.styleable.SupperBubbleLayout_bubble_shadow_color,
                Color.parseColor("#999999"));
        int defShadowSize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX,
                4, getResources().getDisplayMetrics());
        //阴影尺寸
        int shadowSize = ta.getDimensionPixelSize(R.styleable.SupperBubbleLayout_bubble_shadow_size, defShadowSize);
        mRadius = ta.getDimensionPixelSize(R.styleable.SupperBubbleLayout_bubble_radius, 0);
        //三角形方向
        mDirection = ta.getInt(R.styleable.SupperBubbleLayout_bubble_direction, BOTTOM);
        mOffsetUnits = ta.getInt(R.styleable.SupperBubbleLayout_bubble_offset_units, 0);
        mTriangleUnits = ta.getInt(R.styleable.SupperBubbleLayout_bubble_triangle_units, 0);

        ta.recycle();

        mBorderPaint = new Paint();
        mBorderPaint.setAntiAlias(true);
        mBorderPaint.setColor(backGroundColor);
        mBorderPaint.setShadowLayer(shadowSize, 0, 0, shadowColor);

        mPath = new Path();
        mRect = new RectF();
        mDatumPoint = new Point();

        setWillNotDraw(false);
        //关闭硬件加速
        setLayerType(LAYER_TYPE_SOFTWARE, null);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (mDatumPoint.x > 0 && mDatumPoint.y > 0)
            switch (mDirection) {
                case LEFT:
                    drawLeftTriangle(canvas);
                    break;
                case TOP:
                    drawTopTriangle(canvas);
                    break;
                case RIGHT:
                    drawRightTriangle(canvas);
                    break;
                case BOTTOM:
                    drawBottomTriangle(canvas);
                    break;
            }
    }

    private void drawLeftTriangle(Canvas canvas) {
        int triangularLength = mTriangleSize;
        if (triangularLength == 0) {
            return;
        }

        mPath.addRoundRect(mRect, mRadius, mRadius, Path.Direction.CCW);
        mPath.moveTo(mDatumPoint.x, mDatumPoint.y - triangularLength / 2);
        mPath.lineTo(mDatumPoint.x - triangularLength / 2, mDatumPoint.y);
        mPath.lineTo(mDatumPoint.x, mDatumPoint.y + triangularLength / 2);
        mPath.close();
        canvas.drawPath(mPath, mBorderPaint);
    }

    private void drawTopTriangle(Canvas canvas) {
        int triangularLength = mTriangleSize;
        if (triangularLength == 0) {
            return;
        }

        mPath.addRoundRect(mRect, mRadius, mRadius, Path.Direction.CCW);
        mPath.moveTo(mDatumPoint.x + triangularLength / 2, mDatumPoint.y);
        mPath.lineTo(mDatumPoint.x, mDatumPoint.y - triangularLength / 2);
        mPath.lineTo(mDatumPoint.x - triangularLength / 2, mDatumPoint.y);
        mPath.close();
        canvas.drawPath(mPath, mBorderPaint);
    }

    private void drawRightTriangle(Canvas canvas) {
        int triangularLength = mTriangleSize;
        if (triangularLength == 0) {
            return;
        }

        mPath.addRoundRect(mRect, mRadius, mRadius, Path.Direction.CCW);
        mPath.moveTo(mDatumPoint.x, mDatumPoint.y - triangularLength / 2);
        mPath.lineTo(mDatumPoint.x + triangularLength / 2, mDatumPoint.y);
        mPath.lineTo(mDatumPoint.x, mDatumPoint.y + triangularLength / 2);
        mPath.close();
        canvas.drawPath(mPath, mBorderPaint);
    }

    private void drawBottomTriangle(Canvas canvas) {
        int triangularLength = mTriangleSize;
        if (triangularLength == 0) {
            return;
        }

        mPath.addRoundRect(mRect, mRadius, mRadius, Path.Direction.CCW);
        mPath.moveTo(mDatumPoint.x + triangularLength / 2, mDatumPoint.y);
        mPath.lineTo(mDatumPoint.x, mDatumPoint.y + triangularLength / 2);
        mPath.lineTo(mDatumPoint.x - triangularLength / 2, mDatumPoint.y);
        mPath.close();
        canvas.drawPath(mPath, mBorderPaint);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int h = MeasureSpec.getSize(heightMeasureSpec);
        int w = MeasureSpec.getSize(widthMeasureSpec);
        int triangleLen = getSizeFromUnits(mTriangleUnits);
        int rectLeft = getPaddingLeft();
        int rectRight = w - getPaddingRight();
        int rectBottom = h - getPaddingBottom();
        int rectTop = getPaddingTop();
        switch (mDirection) {
            case LEFT:
                rectLeft += triangleLen;
                mDatumPoint.x = rectLeft;
                mDatumPoint.y = h / 2;
                break;
            case TOP:
                rectTop += triangleLen;
                mDatumPoint.x = w / 2;
                mDatumPoint.y = rectTop;
                break;
            case RIGHT:
                rectRight -= triangleLen;
                mDatumPoint.x = rectRight;
                mDatumPoint.y = h / 2;
                break;
            case BOTTOM:
                rectBottom -= triangleLen;
                mDatumPoint.x = w / 2;
                mDatumPoint.y = rectBottom;
                break;
        }
        mTriangleSize = triangleLen;

        mRect.set(rectLeft, rectTop, rectRight, rectBottom);

        if (mOffsetUnits != 0) {
            int offset = getSizeFromUnits(mOffsetUnits);

            switch (mDirection) {
                case LEFT:
                case RIGHT:
                    mDatumPoint.y += offset;
                    break;
                case TOP:
                case BOTTOM:
                    mDatumPoint.x += offset;
                    break;
            }
        }
        View childAt = getChildAt(0);
        if (childAt != null) {
            childAt.measure(
                    MeasureSpec.makeMeasureSpec((int) mRect.width(), MeasureSpec.getMode(widthMeasureSpec)),
                    MeasureSpec.makeMeasureSpec((int) mRect.height(), MeasureSpec.getMode(heightMeasureSpec))
            );
        }
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        View childAt = getChildAt(0);
        if (childAt != null) {
            int cl = (int) mRect.left;
            int ct = (int) mRect.top;
            int cr = (int) mRect.right;
            int cb = (int) mRect.bottom;
            childAt.layout(cl, ct, cr, cb);
        }

    }

    private int getSizeFromUnits(int units) {
        int size;
        ViewGroup.LayoutParams lp = getLayoutParams();
        if (lp instanceof SupperLayout.LayoutParams) {
            SupperLayout.LayoutParams slp = (SupperLayout.LayoutParams) lp;
            size = getMeasuredWidth() * units / slp.widthUnits;
        } else {
            size = units;
        }
        return size;
    }
}
